package com.gframework.core.service.spring;

import java.util.Collection;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 数据字典信息来源抽象类.
 * <p>
 * 本类通常不会单独使用，而是配合 {@link ExtendDataDictionary} 接口一起使用。获取数据字典信息的唯一操作
 * 类永远是 {@link DataDictionary}，你可以通过创建 {@link ExtendDataDictionary} 子类来扩展更多的数据获取方式。<br>
 * 如果你只是简单的使用Map进行存储，可以使用{@link MapDataDictionarySource} 类。
 * </p>
 * <p>
 * 定义一个本类对象的子类，以定义一个数据字典信息获取的操作。
 * 数据字典的存储方式可以是多样的，例如Map，Properties等，这些都由子类自己定义。
 * 甚至也可以不做缓存，每次都从文件或数据库读取。<br>
 * <strong>如果你的数据字典获取类是一个不确定的，经常变化的，每次都需要通过文件、网络等获取的，那么就需要实现{@link DynamicSource} 接口作为标识。
 * 这样{@link DataDictionary} 才不会去缓存数据字典信息。</strong>
 * </p>
 * <p>
 * 本类是对数据字典信息的一种抽象封装，比起直接用Map进行存储，可以按照优先级进行字典数据的读取，
 * 也可以灵活的动态加载不同数据源的字典数据。
 * </p>
 * <p>
 * <strong>本类已经提供有SLF4j的protected的logger对象，子类可以直接使用，无需自己在去创建。</strong>
 * </p>
 * @since 1.0.0
 * @author Ghwolf
 * 
 * @see MapDataDictionarySource
 * @see DataDictionary
 * @see ExtendDataDictionary
 * @see DynamicSource
 */
public abstract class DataDictionarySource {

	protected Logger logger = LoggerFactory.getLogger(getClass());
	/**
	 * 字典类型
	 */
	private final String type;
	
	/**
	 * 创建一个数据字典来源对象，并设置类型
	 * @param type 字典类型
	 * @throws IllegalArgumentException 如果type为null或为空字符串
	 */
	public DataDictionarySource(String type) {
		if (type == null || type.equals("")) {
			throw new IllegalArgumentException("数据字典类型不能是null或\"\"。");
		}
		this.type = type;
	}
	
	/**
	 * 判断是否存在指定的数据code值
	 * @param code 要查询的代码
	 * @return 如果存在返回true，否则返回false
	 */
	public boolean containsData(String code) {
		return getData(code) != null;
	}

	/**
	 * 根据代码值，取得当前类型的字典数据，如果没有，返回null
	 * 
	 * @param code 要查询的代码
	 * @return 返回字典数据，没有返回null
	 */
	public abstract String getData(String code);
	
	/**
	 * 获取所有的字典数据映射关系，以Map方式返回.
	 * <p>
	 * 该方法返回的是一个映射关系副本，而非原始数据，因此如果修改这个Map是无效的。
	 * </p>
	 * @return 返回全部数据字典信息，没有则集合长度为0
	 */
	public abstract Map<String,String> getDataMap() ;
	
	/**
	 * 取得当前类型所有的code值集合
	 * @return 返回所有的code值集合，如果没有，则集合长度为0
	 */
	public abstract Collection<String> getCodes() ;
	
	/**
	 * 取得当前类型所有的value值集合
	 * @return 返回所有的value值集合，如果没有，则集合长度为0
	 */
	public abstract Collection<String> getValues() ;
	
	/**
	 * 取得当前字典数据源的类型
	 * @return 返回类型
	 */
	public String getType() {
		return this.type;
	}

}
